package walasp.proto;

import java.util.Calendar;
import java.util.Date;

import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;

/**
 * Activity for editing an existing Task or creating a new one
 * 
 * 
 */
public class EditActivity extends Activity {
	int mode = 0; // 0 = create, non-zero = modify
	Dialog diag;
	Date fulldate;
	Button calen;
	Spinner statusSpin;
	Calendar cal;
	Uri Contact;
	Boolean Contact_changed;
	Task old = null;
	int CONTACT_PICKER = 7;// 7 because its always 7.

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edittask);
		// this stops null pointer exception when due date is not set
		fulldate = new Date();
		statusSpin = (Spinner) findViewById(R.id.status);

		// get the mode for the activity, defaults to 0
		mode = getIntent().getIntExtra("mode", 0);
		if (mode == 1) {
			Contact_changed = false;
			old = getOldTask();
			if (old == null) {
				Log.e("walasp.proto.EditActivity.onCreate()",
						"old task not set: tid = "
								+ getIntent().getIntExtra("TID", 0));
				finish();
			}
			setFields(old);
		} else if (mode != 0) {
			Log.e("walasp.proto.EditActivity().onCreate()",
					"called with invalid mode");
			finish();
		}

		// due date ticker listener setup
		CheckBox checker = ((CheckBox) findViewById(R.id.notDue));
		checker.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				if (isChecked) {
					//no due date, turn the botton off
					
					calen.setEnabled(false);
				}
				else{
					//turn the button on and ensure the auto date is correct
					calen.setEnabled(true);
					setAutoDueDate();
				}
			}
		});

		// all of the date dialogs variables
		diag = createDiag();
		setupCalendar();
		Button saveBut = (Button) diag.findViewById(R.id.saveButton);
		Button canBut = (Button) diag.findViewById(R.id.cancelButton);
		final DatePicker datePick = (DatePicker) diag.findViewById(R.id.date);
		final TimePicker timePick = (TimePicker) diag.findViewById(R.id.time);
		timePick.setCurrentHour(new Date().getHours() + 1);
		if (old != null && old.getDueDate().getTime() != 0) {
			Date date = old.getDueDate();
			datePick.updateDate(date.getYear() + 1900, date.getMonth(),
					date.getDate());
			timePick.setCurrentMinute(date.getMinutes());
			timePick.setCurrentHour(date.getHours());
		} else {
			datePick.updateDate(datePick.getYear(), datePick.getMonth(),
					datePick.getDayOfMonth() + 1);
		}
		// the listener for the cancel button on the date dialog
		canBut.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// since we're canceling we don't want to save anything
				diag.dismiss();

			}
		});
		// the listener for the save button on the date dialog
		saveBut.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// someone wants to save
				// so we'll get a calendar to put the values into
				cal = Calendar.getInstance();
				// time to put the values into the calendar
				cal.set(datePick.getYear(), datePick.getMonth(),
						datePick.getDayOfMonth(), timePick.getCurrentHour(),
						timePick.getCurrentMinute(), 0);
				// set the date variable with the calendars variables
				fulldate = new Date(cal.getTimeInMillis());

				// set the buttons text to the dates string value
				calen.setText(fulldate.toLocaleString());
				// get rid of the dialog
				diag.dismiss();

			}
		});
		// find the contact add button
		Button conBut = (Button) findViewById(R.id.contactAdd);
		// set its on click listener
		conBut.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// Launch the phones contact picker activity and ensure we can
				// retrieve the selected contact
				Intent intent = new Intent(Intent.ACTION_PICK,
						ContactsContract.Contacts.CONTENT_URI);
				startActivityForResult(intent, CONTACT_PICKER);

			}

		});
	}

	/**
	 * Sets the fields of the view to existing info
	 * 
	 * @requires task != null
	 * @param task
	 *            The task to pull existing info from
	 */
	private void setFields(Task task) {
		if (task == null) {
			Log.e("walasp.proto.EditActivity.setFields()",
					"task.getTaskName() returned null");
			return;
		}
		((EditText) findViewById(R.id.taskName)).setText(task.getTaskName());
		((EditText) findViewById(R.id.description)).setText(task
				.getTaskContent());
		statusSpin.setPrompt(old.getStatus());
		if (old.getStatus().equals(Status.PENDING)) {
			statusSpin.setSelection(1);
		} else if (old.getStatus().equals(Status.FINISHED)) {
			statusSpin.setSelection(2);
		} else if (old.getStatus().equals(Status.CANCELLED)) {
			statusSpin.setEnabled(false);
		} else if (old.getStatus().equals(Status.ACTIVE)) {
			statusSpin.setSelection(0);
		}

		if (task.getContacts() != null) {
			((EditText) findViewById(R.id.contactField))
					.setText(getContactName(task.getContacts()));
		}

		if (task.getDueDate() == null) {

			((CheckBox) findViewById(R.id.notDue)).setChecked(false);

		}
	}

	/**
	 * Returns the task specified by the TID passed into the activity or exits
	 * if not appropriate.
	 * 
	 * @requires mode == 1
	 * @return A Task instance with TID == to TID passed in
	 */
	private Task getOldTask() {
		Task task = null;
		TaskHelper helper = new TaskHelper(getBaseContext());
		task = helper.getTask(getTIDByMode(helper));
		helper.close();
		// will have exited by now unless it's valid, so return it
		return task;
	}

	/** auto populates the fulldate variable and the button text for due date **/
	private void setAutoDueDate() {

		// we want the date to be now + one day, so thats what we do
		cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) + 1);
		fulldate = new Date(cal.getTimeInMillis());
		calen.setText(fulldate.toLocaleString());
	}

	/**
	 * Initialises the various parts of the calendar
	 */
	private void setupCalendar() {
		calen = (Button) findViewById(R.id.date);
		cal = Calendar.getInstance();
		if (old == null) {
			setAutoDueDate();

		} else {
			Date oldDate = old.getDueDate();
			if (oldDate.getTime() == 0) {
				cal.set(Calendar.DAY_OF_MONTH,
						cal.get(Calendar.DAY_OF_MONTH) + 1);
				oldDate = new Date(cal.getTimeInMillis());
				calen.setText(fulldate.toLocaleString());
				oldDate = new Date();
				((CheckBox) findViewById(R.id.notDue)).setChecked(true);
			}
			// should also set the spinner to the right things here
			calen.setText(oldDate.toLocaleString());
		}
		calen.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				diag.show();
			}
		});
	}

	/**
	 * Creates a Dialog for use in the date picker
	 * 
	 * @return the Dialog created
	 */
	private Dialog createDiag() {
		Dialog dialog = new Dialog(this);
		dialog.setContentView(R.layout.datepopup);
		dialog.setTitle("Pick A Date/Time");
		return dialog;
	}

	/**
	 * Listener for the Cancel button on the edit view. Exits without saving.
	 * 
	 * @param view
	 *            View from which listener was called.
	 */

	public void cancelEdit(View view) {
		finish();
	}

	/**
	 * Listener for the Save button on the edit view. Gets the existing task or
	 * creates a new task and sets the content to match. Exits the activity
	 * afterwards.
	 * 
	 * @param view
	 *            View from which listener was called.
	 */
	public void saveTask(View view) {
		TaskHelper helper = new TaskHelper(getBaseContext());
		String name = ((TextView) findViewById(R.id.taskName)).getText()
				.toString();
		String description = ((TextView) findViewById(R.id.description))
				.getText().toString();
		String status;

		status = (String) statusSpin.getSelectedItem();

		if (mode == 1) { // edit
			old.setTaskName(name);
			old.setTaskContent(description);
			if (Contact_changed) {
				old.setContacts(Contact.toString());
			}
			if (status != null) {
				old.setStatus(status);
			}

			if (((CheckBox) findViewById(R.id.notDue)).isChecked()) {
				old.setDueDate(null);
			} else {
				old.setDueDate(fulldate);
			}
			if (!helper.updateTask(old)) {
				Log.e("walasp-proto.EditActivity.saveTask()",
						"UpdateTask() failed");
			}
		} else { // create

			Task task;
			if (Contact != null) {
				task = new Task(helper.getNextTID(), 0, name, description, 1,
						status, Contact.toString(), new Date(), new Date(),
						fulldate, new Date());
			} else {
				task = new Task(helper.getNextTID(), 0, name, description, 1,
						status, null, new Date(), new Date(), fulldate,
						new Date());
			}
			if (((CheckBox) findViewById(R.id.notDue)).isChecked()) {
				task.setDueDate(null);
			}
			if (!helper.insertTask(task)) {
				Log.e("walasp-proto.EditActivity.saveTask()",
						"Insert failed, cancelling creation");
			}
		}
		// clean up connections and exit, regardless of success
		cleanup(helper);
	}

	/**
	 * Closes database connections and exits the activity.
	 * 
	 * @param helper
	 *            The TaskHelper instance to close
	 */
	public void cleanup(TaskHelper helper) {
		helper.close();
		finish();
	}

	/**
	 * Gets the Task ID based on mode, if unable to get correct id for the mode,
	 * exits activity.
	 * 
	 * @param helper
	 *            The TaskHelper instance to cleanup in case of terribleness.
	 * @return the Task ID
	 */
	public int getTIDByMode(TaskHelper helper) {
		int tid = getIntent().getIntExtra("TID", 0);
		if (tid == 0) {
			if (mode == 1) {
				Log.e("walasp-proto.EditActivity.saveTask()",
						"Missing TID for update task, exiting");
				cleanup(helper);
			} else {
				tid = helper.getNextTID();
			}
		}
		return tid;
	}

	@Override
	public void onActivityResult(int reqCode, int resultCode, Intent result) {
		super.onActivityResult(reqCode, resultCode, result);
		if (result == null) {
			return;
		}
		if (reqCode == CONTACT_PICKER) {
			Contact = result.getData();
			Contact_changed = true;
			((EditText) findViewById(R.id.contactField))
					.setText(getContactName(Contact.toString()));
		}

	}

	/**
	 * Used to get Contact Name from a Uri String stored in the task DB
	 * 
	 * @param contact
	 *            A String Representation of an Contact Stored in the Phones
	 *            Contacts
	 * @return the Contact Name
	 */
	private String getContactName(String contact) {
		Uri con = Uri.parse(contact);
		Cursor res = managedQuery(con, null, null, null, null);
		// Cursor res = m
		res.moveToFirst();

		return res.getString(res
				.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

	}
}
